import { Fragment, useEffect, useMemo, useRef, useState } from 'react'
import type { Note, Attachment } from '@/types/notes'
import { notesApi } from '@/services/notesApi'
import { Dialog, Transition } from '@headlessui/react'
import { PlusIcon } from '@heroicons/react/24/solid'
import {
  loadNotes as loadNotesLocal,
  createNote as createNoteLocal,
  deleteNote as deleteNoteLocal,
  fileToAttachment,
  startTiming as startTimingLocal,
  stopTiming as stopTimingLocal,
} from '@/services/notesService'
import socketService from '@/services/socketService'

const fmt = (iso?: string | null) => (iso ? new Date(iso).toLocaleString() : '—')

export default function NotesPage() {
  const [useApi, setUseApi] = useState(true) // 后端可用则使用 API，不可用自动降级

  const [notes, setNotes] = useState<Note[]>([])
  const [title, setTitle] = useState('')
  const [content, setContent] = useState('')
  const [reminderAt, setReminderAt] = useState<string>('')
  const [uploading, setUploading] = useState(false)
  const [newAttachments, setNewAttachments] = useState<Attachment[]>([])
  const [isOpen, setIsOpen] = useState(false)
  const reminderTimer = useRef<number | null>(null)

  // 初始化：优先尝试 API，失败则回退本地（不再使用分组）
  useEffect(() => {
    ;(async () => {
      try {
        const list = await notesApi.listNotes()
        setNotes(list)
        setUseApi(true)
      } catch {
        setNotes(loadNotesLocal())
        setUseApi(false)
      }
    })()
  }, [])

  // Socket: 实时同步（notes_updated）
  useEffect(() => {
    const off = socketService.onNotesUpdated(async () => {
      try {
        if (useApi) {
          const list = await notesApi.listNotes()
          setNotes(list)
        }
      } catch {
        // ignore
      }
    })
    return () => { off && off() }
  }, [useApi])

  // 切换在线/离线时刷新便签（无分组）
  useEffect(() => {
    ;(async () => {
      if (useApi) {
        try {
          const list = await notesApi.listNotes()
          setNotes(list)
        } catch {
          setUseApi(false)
          setNotes(loadNotesLocal())
        }
      } else {
        setNotes(loadNotesLocal())
      }
    })()
  }, [useApi])

  // 简易提醒轮询（与本地实现一致）
  useEffect(() => {
    if (reminderTimer.current) window.clearInterval(reminderTimer.current)
    reminderTimer.current = window.setInterval(() => {
      const now = Date.now()
      ;(useApi ? notes : loadNotesLocal()).forEach(n => {
        if (n.reminderAt) {
          const t = new Date(n.reminderAt).getTime()
          if (t <= now && t + 60_000 > now) {
            if ('Notification' in window) {
              if (Notification.permission === 'granted') {
                new Notification('便签提醒', { body: n.title || n.content.slice(0, 60) || '你有一个提醒' })
              } else if (Notification.permission !== 'denied') {
                Notification.requestPermission()
              }
            }
          }
        }
      })
    }, 30000)
    return () => {
      if (reminderTimer.current) window.clearInterval(reminderTimer.current)
    }
  }, [notes, useApi])

  const filtered = useMemo(() => notes, [notes])



  const onCreateNote = async () => {
    if (useApi) {
      const n = await notesApi.createNote({
        title: title.trim(),
        content: content.trim(),
        reminderAt: reminderAt ? new Date(reminderAt).toISOString() : null,
      })
      // 逐个上传附件
      for (const a of newAttachments) {
        if ((a as any)._file) {
          await notesApi.uploadAttachment(n.id, (a as any)._file as File, a.kind)
        }
      }
      const list = await notesApi.listNotes()
      setNotes(list)
    } else {
      createNoteLocal({
        title: title.trim(),
        content: content.trim(),
        groupId: null,
        reminderAt: reminderAt ? new Date(reminderAt).toISOString() : null,
        attachments: newAttachments,
      })
      setNotes(loadNotesLocal())
    }
    setTitle('')
    setContent('')
    setReminderAt('')
    setNewAttachments([])
  }

  const onAttach = async (files: FileList | null) => {
    if (!files || !files.length) return
    setUploading(true)
    const list: Attachment[] = []
    for (const f of Array.from(files)) {
      const att = await fileToAttachment(f)
      ;(att as any)._file = f // 用于 API 上传
      list.push(att)
    }
    setNewAttachments(prev => [...prev, ...list])
    setUploading(false)
  }

  const onToggleTiming = async (id: string, isTiming: boolean) => {
    if (useApi) {
      // 简化：API 端仅提供累加接口，这里模拟 5 分钟
      await notesApi.addTime(id, isTiming ? 0 : 300)
      const list = await notesApi.listNotes()
      setNotes(list)
    } else {
      if (isTiming) stopTimingLocal(id)
      else startTimingLocal(id)
      setNotes(loadNotesLocal())
    }
  }

  const onDelete = async (id: string) => {
    if (!confirm('确认删除该便签？')) return
    if (useApi) {
      await notesApi.deleteNote(id)
      const list = await notesApi.listNotes()
      setNotes(list)
    } else {
      deleteNoteLocal(id)
      setNotes(loadNotesLocal())
    }
  }

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between gap-3">
        <h1 className="text-2xl font-semibold text-gray-900">便签</h1>
        <div className="flex items-center gap-2">
          {!useApi && <span className="text-xs text-amber-600">离线模式</span>}
        </div>
      </div>

      {/* 悬浮新增按钮 */}
      <button
        className="fixed bottom-6 right-6 h-12 w-12 rounded-full bg-indigo-600 text-white shadow-lg flex items-center justify-center hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
        onClick={() => setIsOpen(true)}
        aria-label="新增便签"
      >
        <PlusIcon className="h-6 w-6" />
      </button>

      {/* 新建便签弹窗 */}
      <Transition.Root show={isOpen} as={Fragment}>
        <Dialog as="div" className="relative z-50" onClose={setIsOpen}>
          <Transition.Child
            as={Fragment}
            enter="ease-out duration-200"
            enterFrom="opacity-0"
            enterTo="opacity-100"
            leave="ease-in duration-150"
            leaveFrom="opacity-100"
            leaveTo="opacity-0"
          >
            <div className="fixed inset-0 bg-black/30" />
          </Transition.Child>

          <div className="fixed inset-0 z-50 overflow-y-auto">
            <div className="flex min-h-full items-end sm:items-center justify-center p-4 text-center">
              <Transition.Child
                as={Fragment}
                enter="ease-out duration-200"
                enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
                enterTo="opacity-100 translate-y-0 sm:scale-100"
                leave="ease-in duration-150"
                leaveFrom="opacity-100 translate-y-0 sm:scale-100"
                leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
              >
                <Dialog.Panel className="w-full max-w-2xl transform overflow-hidden rounded-lg bg-white p-4 text-left align-middle shadow-xl transition-all">
                  <Dialog.Title className="text-lg font-medium text-gray-900">新建便签</Dialog.Title>
                  <div className="mt-3 space-y-3">
                    <div className="grid grid-cols-1 lg:grid-cols-6 gap-3">
                      <input
                        className="input-field lg:col-span-3"
                        placeholder="标题（可选）"
                        value={title}
                        onChange={e => setTitle(e.target.value)}
                      />
                      <input
                        type="datetime-local"
                        className="input-field lg:col-span-3"
                        value={reminderAt}
                        onChange={e => setReminderAt(e.target.value)}
                      />
                      <div className="lg:col-span-6 flex items-center gap-2">
                        <label className="btn btn-sm btn-outline cursor-pointer">
                          添加附件
                          <input
                            type="file"
                            multiple
                            accept="image/*,video/*,audio/*,.pdf,.doc,.docx,.xls,.xlsx,.txt"
                            className="hidden"
                            onChange={e => onAttach(e.target.files)}
                          />
                        </label>
                        {uploading && <span className="text-xs text-gray-500">处理中...</span>}
                      </div>
                    </div>
                    <textarea
                      className="textarea h-40"
                      placeholder="内容（支持文本；图片等小文件可预览，较大文件仅保存元信息/URL）"
                      value={content}
                      onChange={e => setContent(e.target.value)}
                    />
                    {!!newAttachments.length && (
                      <div className="flex flex-wrap gap-2">
                        {newAttachments.map(a => (
                          <div key={a.id} className="border rounded p-2 text-xs">
                            {a.kind === 'image' && (a.dataUrl || a.objectUrl) ? (
                              <img src={a.dataUrl || a.objectUrl} className="w-20 h-20 object-cover rounded mb-1" />
                            ) : (
                              <div className="w-20 h-20 flex items-center justify-center bg-gray-100 rounded mb-1 text-gray-500">
                                {a.kind.toUpperCase()}
                              </div>
                            )}
                            <div className="truncate max-w-[80px]">{a.name}</div>
                          </div>
                        ))}
                      </div>
                    )}
                  </div>
                  <div className="mt-4 flex justify-end gap-2">
                    <button className="btn btn-sm btn-outline" onClick={() => setIsOpen(false)}>取消</button>
                    <button
                      className="btn-primary btn-sm"
                      onClick={async () => {
                        await onCreateNote()
                        setIsOpen(false)
                      }}
                    >
                      保存
                    </button>
                  </div>
                </Dialog.Panel>
              </Transition.Child>
            </div>
          </div>
        </Dialog>
      </Transition.Root>

      {/* 网格 */}
      <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-3">
        {filtered.map(n => (
          <div key={n.id} className="card p-3 space-y-2">
            <div className="flex items-start justify-between gap-2">
              <div>
                <div className="font-semibold text-gray-900 truncate">{n.title || '（无标题）'}</div>
                <div className="text-xs text-gray-500">{fmt(n.updatedAt)}</div>
              </div>
              <div className="text-right">
                {n.reminderAt && (
                  <div className="text-[10px] text-amber-600">提醒 {fmt(n.reminderAt)}</div>
                )}
              </div>
            </div>
            <div className="text-sm text-gray-700 whitespace-pre-wrap break-words line-clamp-6">
              {n.content}
            </div>
            {!!n.files?.length && (
              <div className="flex flex-wrap gap-2">
                {n.files.slice(0, 3).map(a => (
                  <div key={a.id} className="w-20 h-20 rounded overflow-hidden bg-gray-100 flex items-center justify-center">
                    {a.kind === 'image' ? (
                      <img src={a.url} className="w-full h-full object-cover" />
                    ) : (
                      <span className="text-[10px] text-gray-500 px-1">{a.kind.toUpperCase()}</span>
                    )}
                  </div>
                ))}
                {n.files.length > 3 && (
                  <div className="w-20 h-20 rounded bg-gray-100 text-xs text-gray-600 flex items-center justify-center">
                    +{n.files.length - 3}
                  </div>
                )}
              </div>
            )}
            <div className="flex items-center justify-between text-xs text-gray-600">
              <div>累计 {Math.floor((n.timeSpent || 0) / 60)} 分</div>
              <div className="flex items-center gap-2">
                <button
                  className="btn btn-xs"
                  onClick={() => onToggleTiming(n.id, false)}
                >
                  增加5分钟
                </button>
                <button
                  className="btn btn-xs btn-outline"
                  onClick={() => onDelete(n.id)}
                >
                  删除
                </button>
              </div>
            </div>
          </div>
        ))}
        {!filtered.length && (
          <div className="col-span-full text-center text-gray-500 text-sm py-6">
            暂无便签
          </div>
        )}
      </div>
    </div>
  )
}